package com.dman.multi.ui;

import java.net.Proxy;
import java.net.Proxy.Type;
import java.net.URL;
import java.nio.channels.UnresolvedAddressException;

import org.apache.pivot.beans.BXML;
import org.apache.pivot.beans.Bindable;
import org.apache.pivot.collections.ArrayList;
import org.apache.pivot.collections.List;
import org.apache.pivot.collections.Map;
import org.apache.pivot.util.Resources;
import org.apache.pivot.util.Vote;
import org.apache.pivot.wtk.BoxPane;
import org.apache.pivot.wtk.Button;
import org.apache.pivot.wtk.Button.State;
import org.apache.pivot.wtk.ButtonGroup;
import org.apache.pivot.wtk.ButtonPressListener;
import org.apache.pivot.wtk.Checkbox;
import org.apache.pivot.wtk.Dialog;
import org.apache.pivot.wtk.DialogStateListener;
import org.apache.pivot.wtk.ListButton;
import org.apache.pivot.wtk.Prompt;
import org.apache.pivot.wtk.PushButton;
import org.apache.pivot.wtk.RadioButton;
import org.apache.pivot.wtk.TextInput;

import com.dman.multi.core.DownloadSettings;
import com.dman.multi.core.ProxySettings;

public class Settings extends Dialog implements Bindable {
	
	@BXML private TextInput maxConcurrentDownloads;
	@BXML private ListButton connectionSpeed;
	@BXML private Checkbox setupProxy;
	@BXML private TextInput proxyHost;
	@BXML private TextInput proxyPort;
	@BXML private ButtonGroup proxyType;
	@BXML private Checkbox proxyAuth;
	@BXML private TextInput proxyUser;
	@BXML private TextInput proxyPass;
	@BXML private BoxPane ptype;
	@BXML private RadioButton socks;
	@BXML private RadioButton http;
	@BXML private PushButton okButton;
	@BXML private PushButton cancelButton;
	
	private List<String> listData = null;	
	private static DownloadSettings downloadSettings = null;

	@Override
	public void initialize(Map<String, Object> namespace, URL location, Resources resources) {
		// setup proxy listener
		setupProxy.getButtonPressListeners().add(new ButtonPressListener() {			
			@Override
			public void buttonPressed(Button button) {
				State st = button.getState();
				switch (st) {
				case SELECTED:
					proxyHost.setEnabled(true);
					proxyPort.setEnabled(true);
					ptype.setEnabled(true);
					break;
				default:
					proxyHost.setEnabled(false);
					proxyPort.setEnabled(false);
					ptype.setEnabled(false);
					break;
				}
			}
		});
		
		// populate list data, for list button
		if(listData == null){
			listData = new ArrayList<String>();
			listData.add("56 kbps");
			listData.add("144 kbps");
			listData.add("256 kbps");
			listData.add("512 kbps");
			listData.add("1 mbps");
			listData.add("2 mbps");
			listData.add("3 mbps");
			listData.add("4 mbps");
			listData.add("5 mbps");
			listData.add("6 mbps");
			listData.add("7 mbps");
			listData.add("8 mbps");
			listData.add("10 mbps");
			listData.add("12 mbps");
			listData.add("16 mbps");
			listData.add("20 mbps");
			listData.add("32 mbps");
			listData.add("40 mbps");
			listData.add("50 mbps");
			listData.add("64 mbps");
			listData.add("100 mbps");
			listData.add("128 mbps");
			connectionSpeed.setListData(listData);
			connectionSpeed.setSelectedItem(listData.get(3));
		}
		
		// handle ok cancel
		okButton.getButtonPressListeners().add(new ButtonPressListener() {			
			@Override
			public void buttonPressed(Button button) {
				Settings.this.close(true);
			}
		});
		cancelButton.getButtonPressListeners().add(new ButtonPressListener() {			
			@Override
			public void buttonPressed(Button button) {
				Settings.this.close(false);
			}
		});
		
		// handle dialog close
		this.getDialogStateListeners().add(new DialogStateListener.Adapter(){
			@Override
			public Vote previewDialogClose(Dialog dialog, boolean result) {
				
				// check if download settings are null and result is false
				if(downloadSettings == null && result == false)
					return Vote.DENY;
				
				// check max concurrent downloads
				if(!maxConcurrentDownloads.getText().matches("[1-9]")){
					Prompt.prompt("Max. concurrent downloads must be a number between 1 & 9", Settings.this);
					return Vote.DENY;
				}
				
				// create maxConcurrent downloads and connection speed
				ProxySettings ps = null;
				int maxCon = Integer.parseInt(maxConcurrentDownloads.getText());
				String selSpeed = (String) connectionSpeed.getSelectedItem();
				
				// check for proxy state
				State st = setupProxy.getState();
				if(st == State.SELECTED){
					if(proxyType.getSelection() == null) {
						Prompt.prompt("Proxy type must be specified", Settings.this);
						return Vote.DENY;
					}
					
					try{
						// obtain data from the UI
						String host = proxyHost.getText();
						int port = Integer.valueOf(proxyPort.getText());
						
						// select the proxy type and create proxy
						Proxy.Type pt = Proxy.Type.HTTP;
						if(proxyType.getSelection().equals(socks))
							pt = Proxy.Type.SOCKS;
						
						// create the download settings
						String userName = proxyUser.getText();
						String password = proxyPass.getText();

						ps = new ProxySettings(host, port, pt, proxyAuth.getState() == State.SELECTED, userName, password);
					} catch (NumberFormatException nfe){
						Prompt.prompt("Invalid port number specified", Settings.this.getOwner());
						return Vote.DENY;
					} catch (UnresolvedAddressException uae){
						Prompt.prompt("Unable to resolve the specified proxy", Settings.this.getOwner());
						return Vote.DENY;
					}
					
				}
				
											
				if(result)
					setSettings(Settings.this, new DownloadSettings(maxCon, selSpeed, ps));
				
				return Vote.APPROVE;
			}
		});
		
		// pre-populate settings dialog if settings is present
		if(downloadSettings != null){
			maxConcurrentDownloads.setText(downloadSettings.getMaxConcurrentDownloads() + "");
			connectionSpeed.setSelectedItem(downloadSettings.getConnectionSpeed());
			ProxySettings ps = downloadSettings.getProxySettings();
			if(ps != null){
				setupProxy.setState(State.SELECTED);
				proxyHost.setText(ps.getProxyHost());
				proxyPort.setText(ps.getProxyPort() + "");
				proxyUser.setText(ps.getUserName());
				proxyPass.setText(ps.getEncryptedPassword());
				proxyType.setSelection(http);
				if(ps.getProxyType() == Type.SOCKS)
					proxyType.setSelection(socks);
			}
		}
		
	}
	
	public static DownloadSettings getSettings(){		
		return downloadSettings;
	}
	
	public static void setSettings(Settings settingsDialog, DownloadSettings ds){
		if(downloadSettings == null)
			downloadSettings = ds;

		synchronized (downloadSettings) {
			downloadSettings.setConnectionSpeed(ds.getConnectionSpeed());
			downloadSettings.setMaxConcurrentDownloads(ds.getMaxConcurrentDownloads());
			downloadSettings.setProxySettings(ds.getProxySettings());
			downloadSettings.notifyAll();
		}
		settingsDialog.maxConcurrentDownloads.setText(ds.getMaxConcurrentDownloads() + "");
		settingsDialog.connectionSpeed.setSelectedItem(downloadSettings.getConnectionSpeed());
		ProxySettings ps = downloadSettings.getProxySettings();
		settingsDialog.setupProxy.setState(ps == null?State.UNSELECTED:State.SELECTED);
		boolean enabled = false;
		if(ps != null)
			enabled = true;
		settingsDialog.proxyHost.setEnabled(enabled);
		settingsDialog.proxyPort.setEnabled(enabled);
		settingsDialog.ptype.setEnabled(enabled);
		settingsDialog.proxyUser.setEnabled(false);
		settingsDialog.proxyPass.setEnabled(false);
		settingsDialog.proxyAuth.setEnabled(enabled);
		if(enabled){
			settingsDialog.proxyHost.setText(ps.getProxyHost());
			settingsDialog.proxyPort.setText(ps.getProxyPort() + "");
			settingsDialog.proxyType.setSelection(settingsDialog.http);
			if(ps.getProxyType() == Type.SOCKS)
				settingsDialog.proxyType.setSelection(settingsDialog.socks);
			enabled = ps.isAuthSpecified();
			settingsDialog.proxyAuth.setState(enabled?State.SELECTED:State.UNSELECTED);
			settingsDialog.proxyUser.setEnabled(enabled);
			settingsDialog.proxyPass.setEnabled(enabled);
			if(enabled){
				settingsDialog.proxyUser.setText(ps.getUserName());
				settingsDialog.proxyPass.setText(ps.getEncryptedPassword());
			}
		}
	}

}
